using System;

namespace SharpMud.MudLib.SAMPLE.Entities
{
#if !Use_Common_MudLib
	public class PlayerSystem
	{
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType);

		#region Private Variables
		private PlayerMetabase								_Players;
		private MudLib.SAMPLE.MudLibRoot						_Host;
		private MudLib.SAMPLE.Entities.PlayerCreationManager _PlayerCreation;
		#endregion

		#region Public Properties
		public PlayerMetabase Players
		{
			get
			{
				return _Players;
			}
		}
		public MudLib.SAMPLE.MudLibRoot Host
		{
			get
			{
				return _Host;
			}
		}
		public MudLib.SAMPLE.Entities.PlayerCreationManager PlayerCreation
		{
			get
			{
				return this._PlayerCreation;
			}
		}
		/// <summary>
		/// The root folder where all the Player files should be kept.
		/// </summary>
		public string RootPlayerFolder
		{
			get
			{
				return MudLibRoot.GetSubfolderIntelligently(this.Host.RootEntitiesFolder,"Players");
			}
		}
		#endregion

		#region Public Methods

		public void Shutdown()
		{
			log.Info("Shutting down...");
			this.Players.CloseAllPlayers(true);
			this._Players = null;
			log.Info("STOPPED.");
		}

		public void Startup()
		{
			log.Info("Starting up...");
			this._Players = new PlayerMetabase(this);
			this.Players.LoadAllPlayers(true,false);
			log.Info("STARTED.");
		}
		public bool IsValidName(string playerName)
		{
			playerName = playerName.Trim();
			foreach(char c in playerName.ToCharArray())
			{
				if(Char.IsLetter(c))
					continue;
				if(Char.IsWhiteSpace(c))
					return false;
				if(Char.IsSymbol(c))
					return false;
				if(!Char.IsLetterOrDigit(c))
					return false;
				if(Char.IsNumber(c))
					return false;
			}
			return true;
		}
		public bool IsValidEmailAddress(string emailAddress)
		{
			string emailRegex = "[a-zA-Z]*[a-zA-Z0-9]*@*.*";
			if(System.Text.RegularExpressions.Regex.Match(emailAddress,emailRegex).Length!=0)
				return true;
			else
				return false;
		}
		public bool IsValidPassword(string password)
		{
			if(password==String.Empty)
				return false;
			if(password!=password.Trim())
				return false;
			return true;
		}
		#endregion

		#region Constructors
		private PlayerSystem()
		{
			_Players = new PlayerMetabase(this);
			_PlayerCreation = new PlayerCreationManager();
			_LoggedOnPlayers = new System.Collections.ArrayList();
			_PlayingPlayers = new System.Collections.ArrayList();
		}

		public PlayerSystem(MudLib.SAMPLE.MudLibRoot host)
			:this()
		{
			_Host = host;
		}
		#endregion

		#region Logon/Logoff Tracking
		private System.Collections.ArrayList _LoggedOnPlayers;

		/// <summary>
		/// Determines if the given player is logged into the system with an interactive session
		/// </summary>
		/// <param name="player"></param>
		/// <returns></returns>
		public bool IsPlayerLoggedOn(PlayerCharacter player)
		{
			return IsPlayerLoggedOn(player.PlayerName);
		}

		/// <summary>
		/// Determines if the player by the given name is logged into the system with an
		/// interactive session
		/// </summary>
		/// <param name="playerName"></param>
		/// <returns></returns>
		public bool IsPlayerLoggedOn(string playerName)
		{
			if(!this.Players.PlayerExists(playerName))
				throw new PlayerNotFoundException();
			foreach(PlayerCharacter pc in _LoggedOnPlayers)
			{
				if(pc.PlayerName.Trim().ToLower()==playerName.Trim().ToLower())
					return true;
			}
			return false;
		}

		/// <summary>
		/// Tells the player system that the given player is logged into the system with an
		/// interactive session
		/// </summary>
		/// <param name="player"></param>
		internal void RegisterPlayerLogon(PlayerCharacter player)
		{
			this._LoggedOnPlayers.Add(player);
		}

		/// <summary>
		/// Tells the player system that the given player is no longer logged into the system with
		/// an interactive session
		/// </summary>
		internal void RegisterPlayerLogoff(PlayerCharacter player)
		{
//			foreach(PlayerCharacter c in this._LoggedOnPlayers)
//			{
//				if(c.PlayerName.Trim().ToLower()==player.PlayerName.Trim().ToLower())
//				{
//					_LoggedOnPlayers.Remove(c);
//				}
//			}
			if(_LoggedOnPlayers.Contains(player))
				_LoggedOnPlayers.Remove(player);
		}

		/// <summary>
		/// Gets all players that are currently logged into the system with an interactive session
		/// </summary>
		public PlayerCharacter[] LoggedOnPlayers
		{
			get
			{
				return (PlayerCharacter[])this._LoggedOnPlayers.ToArray(typeof(PlayerCharacter));
			}
		}
		#endregion

		#region Playing/NotPlaying Tracking
		private System.Collections.ArrayList _PlayingPlayers;

		/// <summary>
		/// Determines if the given player is currently in the game world
		/// </summary>
		public bool IsPlayerPlaying(PlayerCharacter player)
		{
			return IsPlayerPlaying(player.PlayerName);
		}

		/// <summary>
		/// Determines if the player by the given name is currently in the game world
		/// </summary>
		public bool IsPlayerPlaying(string playerName)
		{
			if(!this.Players.PlayerExists(playerName))
				throw new PlayerNotFoundException();
			foreach(PlayerCharacter pc in _PlayingPlayers)
			{
				if(pc.PlayerName.Trim().ToLower()==playerName.Trim().ToLower())
					return true;
			}
			return false;
		}

		/// <summary>
		/// Tells the PlayerSystem that the given player is in the game world
		/// </summary>
		internal void RegisterPlayerPlaying(PlayerCharacter player)
		{
			this._PlayingPlayers.Add(player);
		}

		/// <summary>
		/// Tells the PlayerSystem that the given player is no longer in the game world
		/// </summary>
		internal void RegisterPlayerNotPlaying(PlayerCharacter player)
		{
			if(!this._PlayingPlayers.Contains(player))
				return;
			this._PlayingPlayers.Remove(player);
		}

		/// <summary>
		/// Gets all player characters that are in the game world
		/// </summary>
		public PlayerCharacter[] PlayingPlayers
		{
			get
			{
				return (PlayerCharacter[])this._PlayingPlayers.ToArray(typeof(PlayerCharacter));
			}
		}
		#endregion
	}
#endif
}
